package com.example.rbac.service;

import com.example.rbac.common.RequestHolder;
import com.example.rbac.dao.SysDeptMapper;
import com.example.rbac.dao.SysUserMapper;
import com.example.rbac.exception.BusinessException;
import com.example.rbac.exception.ParamException;
import com.example.rbac.model.SysDept;
import com.example.rbac.param.DeptParam;
import com.example.rbac.util.BeanValidator;
import com.example.rbac.util.IpUtil;
import com.example.rbac.util.LevelUtil;
import com.google.common.base.Preconditions;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

/**
 * @author XieLongzhen
 * @date 2018/12/28 18:50
 */
@Slf4j
@Service
public class SysDeptService {

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysLogService sysLogService;

    public boolean save(DeptParam param) {
        try {
            BeanValidator.check(param);
            if (checkExist(param.getParentId(), param.getName(), param.getId())) {
                throw new ParamException("同一层级下存在相同名称的部门");
            }
            SysDept sysDept = SysDept.builder().name(param.getName()).parentId(param.getParentId())
                    .seq(param.getSeq()).remark(param.getRemark()).remark("a").build();
            sysDept.setLevel(LevelUtil.calculateLevel(getLevel(param.getParentId()), param.getParentId()));
            sysDept.setOperator(RequestHolder.getCurrentUser().getUsername());
            sysDept.setOperateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()));
            sysDept.setOperateTime(new Date());

            if (sysDeptMapper.insertSelective(sysDept) > 0) {
                sysLogService.saveDeptLog(null, sysDept);
                return true;
            }
            return false;
        } catch (Exception e) {
            log.info("Add SysDept Failed: {}", e);
            throw new RuntimeException("新增部门时出错！系统异常");
        }
    }

    @Transactional
    public boolean update(DeptParam param) {
        try {
            BeanValidator.check(param);
            if (checkExist(param.getParentId(), param.getName(), param.getId())) {
                throw new ParamException("同一层级下存在相同名称的部门");
            }
            SysDept before = sysDeptMapper.selectByPrimaryKey(param.getId());
            Preconditions.checkNotNull(before, "待更新部门不存在");

            SysDept after = SysDept.builder().id(param.getId()).name(param.getName())
                    .parentId(param.getParentId()).seq(param.getSeq()).remark(param.getRemark())
                    .level(LevelUtil.calculateLevel(getLevel(param.getParentId()), param.getParentId()))
                    .operator(RequestHolder.getCurrentUser().getUsername())
                    .operateIp(IpUtil.getRemoteIp(RequestHolder.getCurrentRequest()))
                    .operateTime(new Date()).build();
            updateWithChild(before, after);
            return true;
        } catch (Exception e) {
            log.info("更新部门失败:{}", e);
            throw new BusinessException("更新部门失败！");
        }
    }

    private void updateWithChild(SysDept before, SysDept after) {
        String newLevelPrefix = after.getLevel();
        String oldLevelPrefix = before.getLevel();
        if (!newLevelPrefix.equals(oldLevelPrefix)) {
            List<SysDept> deptList = sysDeptMapper.selectChildDeptListByLevel(before.getLevel());
            if (CollectionUtils.isNotEmpty(deptList)) {
                for (SysDept dept : deptList) {
                    String level = dept.getLevel();
                    if (level.indexOf(oldLevelPrefix) == 0) {
                        level = newLevelPrefix + level.substring(oldLevelPrefix.length());
                        dept.setLevel(level);
                    }
                }
                sysDeptMapper.batchUpdateDeptList(deptList);
            }
        }
        sysDeptMapper.updateByPrimaryKey(after);
        sysLogService.saveDeptLog(before, after);
    }

    private boolean checkExist(Integer parentId, String deptName, Integer deptId) {
        SysDept dept = SysDept.builder().parentId(parentId).name(deptName).id(deptId).build();
        return sysDeptMapper.checkExist(dept) > 0;
    }

    private String getLevel(Integer deptId) {
        SysDept sysDept = sysDeptMapper.selectByPrimaryKey(deptId);
        if (sysDept == null) {
            return null;
        }
        return sysDept.getLevel();
    }

    public void delete(int deptId) {
        SysDept dept = sysDeptMapper.selectByPrimaryKey(deptId);
        Preconditions.checkNotNull(dept, "待删除的部门不存在，无法删除");
        if (sysDeptMapper.countDeptListSelective(SysDept.builder().parentId(deptId).build()) > 0) {
            throw new ParamException("当前部门下面有子部门，无法删除");
        }
        if (sysUserMapper.countByDeptId(dept.getId()) > 0) {
            throw new ParamException("当前部门下面有用户，无法删除");
        }
        sysDeptMapper.deleteByPrimaryKey(deptId);

    }
}
